﻿namespace Microsoft.VisualStudio.ServiceModel.DomainServices.Tools
{
    using Microsoft.ServiceModel.DomainServices.Tools;
    using System;
    using System.Data.Metadata.Edm;
    using System.Data.Objects;
    using System.Linq;
    using System.Reflection;
    using System.ServiceModel.DomainServices.EntityFramework;

    internal class LinqToEntitiesEntity : BusinessLogicEntity
    {
        private string _defaultObjectSetName;
        private System.Data.Metadata.Edm.EntityType _entityType;
        private bool _hasTimestampMember;
        private bool _isDbContext;

        public LinqToEntitiesEntity(LinqToEntitiesContextBase context, System.Data.Metadata.Edm.EntityType entityType, Type type) : base(context, entityType.Name, type)
        {
            this._hasTimestampMember = (from p in entityType.Members
                where System.ServiceModel.DomainServices.EntityFramework.ObjectContextUtilities.IsConcurrencyTimestamp(p)
                select p).Count<EdmMember>() == 1;
            this._entityType = entityType;
            this._isDbContext = context is LinqToEntitiesDbContext;
        }

        private string FindDefaultObjectSetName()
        {
            foreach (PropertyInfo info in base.BusinessLogicContext.ContextType.GetProperties())
            {
                Type propertyType = info.PropertyType;
                if (propertyType.IsGenericType)
                {
                    Type[] genericArguments = propertyType.GetGenericArguments();
                    if (((genericArguments.Length == 1) && this.IsContextSetType(propertyType)) && !(base.ClrType != genericArguments[0]))
                    {
                        return info.Name;
                    }
                }
            }
            return null;
        }

        private bool IsContextSetType(Type t)
        {
            if (this._isDbContext)
            {
                return DbContextUtilities.CompareWithSystemType(t, "System.Data.Entity.DbSet`1");
            }
            return (t.GetGenericTypeDefinition() == typeof(ObjectSet<>));
        }

        public override bool CanBeIncluded
        {
            get
            {
                return ((this.DefaultObjectSetName != null) && base.CanBeIncluded);
            }
        }

        public string DefaultObjectSetName
        {
            get
            {
                if (this._defaultObjectSetName == null)
                {
                    this._defaultObjectSetName = this.FindDefaultObjectSetName();
                }
                return this._defaultObjectSetName;
            }
        }

        public System.Data.Metadata.Edm.EntityType EntityType
        {
            get
            {
                return this._entityType;
            }
        }

        public bool HasTimestampMember
        {
            get
            {
                return this._hasTimestampMember;
            }
        }
    }
}

